This is an R Markdown Notebook to study boundary layer meteorology.

Create the dataset - - From Great Plains Field Prpgram at O’Neil Nebraska

TatDpoint025 <- c(25.54,24.84,25.77,29.42,33.25,35.25,34.84,32.63,30.07,28.42,27.09,26.09,25.30)
TatDpoint05 <- c(26.00,25.30,25.35,27.36,30.32,32.63,33.20,32.05,30.20,28.74,27.50,26.60,25.83)
TatDpoint10 <- c(26.42,25.84,25.42,25.98,27.62,29.52,30.62,30.62,29.91,28.84,27.84,27.06,26.40)
TatDpoint20 <- c(26.32,25.97,25.56,25.39,25.57,26.11,26.88,27.41,27.68,27.57,27.22,26.87,26.53)
TatDpoint40 <- c(24.50,24.48,24.36,24.34,24.27,24.24,24.26,24.32,24.47,24.64,24.73,24.78,24.84)
datetime <- c('2015-08-31 04:35','2015-08-31 06:35','2015-08-31 08:35','2015-08-31 10:35','2015-08-31 12:35','2015-08-31 14:35','2015-08-31 16:35','2015-08-31 18:35','2015-08-31 20:35','2015-08-31 22:35','2015-09-01 00:35','2015-09-01 02:35','2015-09-01 04:35')   
blaygpfp <- data.frame(TatDpoint025,TatDpoint05,TatDpoint10,TatDpoint20,TatDpoint40,datetime)

check the data

#convert the date format
blaygpfp$datetime<- as.POSIXct(blaygpfp$datetime, "%Y-%m-%d %H:%M",tz="US/Pacific")
unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
#TODO Take the annnoying date fotmat error out
str(blaygpfp)
'data.frame':   13 obs. of  6 variables:
 $ TatDpoint025: num  25.5 24.8 25.8 29.4 33.2 ...
 $ TatDpoint05 : num  26 25.3 25.4 27.4 30.3 ...
 $ TatDpoint10 : num  26.4 25.8 25.4 26 27.6 ...
 $ TatDpoint20 : num  26.3 26 25.6 25.4 25.6 ...
 $ TatDpoint40 : num  24.5 24.5 24.4 24.3 24.3 ...
 $ datetime    : POSIXct, format: 
unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
"2015-08-31 04:35:00" "2015-08-31 06:35:00" "2015-08-31 08:35:00" ...

Plot the data

plot(blaygpfp)

library(ggplot2)
library(dplyr)
library(reshape)

Attaching package: ‘reshape’

The following object is masked from ‘package:dplyr’:

    rename

Plot Temperature waves as function of time and depth.

blaygpfp %>% ggplot() +
geom_point(aes(x=datetime,y=TatDpoint025,colour = as.factor(0.025), shape=as.factor(0))) +
  stat_smooth(aes(x = datetime, y = TatDpoint025), se = FALSE) +
geom_point(aes(x=datetime,y=TatDpoint05,colour = as.factor(0.05))) +
  stat_smooth(aes(x = datetime, y = TatDpoint05), se = FALSE) +
geom_point(aes(x=datetime,y=TatDpoint10,colour = as.factor(0.10))) +
  stat_smooth(aes(x = datetime, y = TatDpoint10), se = FALSE) +
geom_point(aes(x=datetime,y=TatDpoint20,colour = as.factor(0.20))) +
stat_smooth(aes(x = datetime, y = TatDpoint20), se = FALSE) +
geom_point(aes(x=datetime,y=TatDpoint40,colour = as.factor(0.40))) +
stat_smooth(aes(x = datetime, y = TatDpoint40), se = FALSE) +
labs(colour = "Depth")  +
xlab("Date") + ylab("Temperature")

# check if line plot is better

With markers

#normalize temperature
blaygpfp %>% ggplot() +
geom_point(aes(x=datetime,y=TatDpoint025, shape=as.factor(0.025))) +
  geom_line(aes(x = datetime, y = TatDpoint025)) +
geom_point(aes(x=datetime,y=TatDpoint05,shape = as.factor(0.05))) +
  geom_line(aes(x = datetime, y = TatDpoint05)) +
geom_point(aes(x=datetime,y=TatDpoint10,shape = as.factor(0.10))) +
  geom_line(aes(x = datetime, y = TatDpoint10),) +
geom_point(aes(x=datetime,y=TatDpoint20,shape = as.factor(0.20))) +
geom_line(aes(x = datetime, y = TatDpoint20)) +
geom_point(aes(x=datetime,y=TatDpoint40,shape = as.factor(0.40))) +
geom_line(aes(x = datetime, y = TatDpoint40)) +
labs(colour = "Depth")  +
xlab("Date") + ylab("Temperature")+
ggtitle("Temperatures waves - function of time and depth")  

# check if line plot is better

Housekeeping

# reshape it
blaygpfp_melt <- melt(blaygpfp,id="datetime")
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
# set the depth
blaygpfp_melt$depth <- 0
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
blaygpfp_melt[blaygpfp_melt$variable=='TatDpoint05',]$depth = 0.05
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
blaygpfp_melt[blaygpfp_melt$variable=='TatDpoint10',]$depth = 0.10
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
blaygpfp_melt[blaygpfp_melt$variable=='TatDpoint20',]$depth = 0.20
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
blaygpfp_melt[blaygpfp_melt$variable=='TatDpoint40',]$depth = 0.40
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
blaygpfp_melt[blaygpfp_melt$variable=='TatDpoint025',]$depth = 0.025
Warning in as.POSIXlt.POSIXct(x, tz) :
  unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
library(lubridate)

Attaching package: ‘lubridate’

The following object is masked from ‘package:reshape’:

    stamp

The following object is masked from ‘package:base’:

    date
#In check_tzones(e1, e2) : 'tzone' attributes are inconsistent
blaygpfp_melt$datetime <- ymd_hms(blaygpfp_melt$datetime)
unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'
#Do increment of the time intervals
blaygpfp_melt %>% filter(datetime == ymd_hms("2015-09-01 04:35:00")) 
# set the time intervals
 blaygpfp_melt$interval <- 0
blaygpfp_melt[datetime == ymd_hms("2015-08-31 06:35:00"), ]$interval<- 2
blaygpfp_melt[datetime == ymd_hms("2015-08-31 08:35:00"), ]$interval<- 4
blaygpfp_melt[datetime == ymd_hms("2015-08-31 10:35:00"), ]$interval<- 6
blaygpfp_melt[datetime == ymd_hms("2015-08-31 12:35:00"), ]$interval<- 8
blaygpfp_melt[datetime == ymd_hms("2015-08-31 14:35:00"), ]$interval<- 10
blaygpfp_melt[datetime == ymd_hms("2015-08-31 16:35:00"), ]$interval<- 12
blaygpfp_melt[datetime == ymd_hms("2015-08-31 18:35:00"), ]$interval<- 14
blaygpfp_melt[datetime == ymd_hms("2015-08-31 20:35:00"), ]$interval<- 16
blaygpfp_melt[datetime == ymd_hms("2015-08-31 22:35:00"), ]$interval<- 18
blaygpfp_melt[datetime == ymd_hms("2015-09-01 00:35:00"), ]$interval<- 20
blaygpfp_melt[datetime == ymd_hms("2015-09-01 02:35:00"), ]$interval<- 22
blaygpfp_melt[datetime == ymd_hms("2015-09-01 04:35:00"), ]$interval<- 24
#'data.frame':  65 obs. of  3 variables:
# $ datetime: POSIXct, format: "2015-08-31 04:35:00" "2015-08-31 06:35:00"  #$ variable: Factor w/ 5 levels "TatDpoint025",..: 1 1 1 1 1 1 1 1 1 1 ...
# $ value   : num  25.5 24.8 25.8 29.4 33.2 ...

Plot Time waves as function of depth and temperature

#normalize temperature
blaygpfp_melt$scaleT <- scale(blaygpfp_melt$value)  %>% as.vector()
# We want for hours 0, 4,8,12,16,20
blaygpfp_melt  %>% filter(interval %in% c(0, 4,8,12,16,20)) %>%  ggplot() +
geom_point(aes(x=value,y=depth,color=as.factor(interval),shape=as.factor(interval)))+
   
#geom_line(aes(x=value,y=depth,color=as.factor(interval),shape=as.factor(interval)))+
stat_smooth(aes(x=value,y=depth,color=as.factor(interval),shape=as.factor(interval)))+  
xlab("Temperature(deg C)") + ylab("Depth")+
ggtitle("Temperatures at various times - function of z and T")  
Ignoring unknown aesthetics: shape

# check if line plot is better

plot for depth

library(ggplot2)
amp <- c(5,3.6,2.5,1.5,.5)
depth <- c(0.025,0.05,.1,.2,.4)
plotampdepthdf <- data.frame(depth,amp)
lm_eqn <- function(df){
    m <- lm(amp ~ depth, df);
    eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
         list(a = format(coef(m)[1], digits = 2), 
              b = format(coef(m)[2], digits = 2), 
             r2 = format(summary(m)$r.squared, digits = 3)))
    as.character(as.expression(eq));                 
}
p <- ggplot(data = plotampdepthdf, aes(x = depth, y = amp)) +
            geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x) +
            geom_point()
p1 <- p + geom_text(x = 0.2, y = 3, label = lm_eqn(plotampdepthdf), parse = TRUE)
p1

With log Amp

library(ggplot2)
amp <- c(5,3.6,2.5,1.5,.5)
depth <- c(0.025,0.05,.1,.2,.4)
amp <- log(amp)
plotampdepthdf <- data.frame(depth,amp)
lm_eqn <- function(df){
    m <- lm(amp ~ depth, df);
    eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
         list(a = format(coef(m)[1], digits = 2), 
              b = format(coef(m)[2], digits = 2), 
             r2 = format(summary(m)$r.squared, digits = 3)))
    as.character(as.expression(eq));                 
}
p <- ggplot(data = plotampdepthdf, aes(x = depth, y = amp)) +
            geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x) +
            geom_point()
p1 <- p + geom_text(x = 0.2, y = .5, label = lm_eqn(plotampdepthdf), parse = TRUE)+
    xlab("Depth") + ylab("log(amplitude)") + ggtitle("Log of Amplitude")
p1

Lets try a polynomial fit

lm(y ~ poly(x, 3, raw=TRUE))

amp <- c(5,3.6,2.5,1.5,.5)
depth <- c(0.025,0.05,.1,.2,.4)
plotampdepthdf <- data.frame(depth,amp)
poly.model <-lm(amp ~ poly(depth,3,raw=TRUE), df)
summary(poly.model)

Call:
lm(formula = amp ~ poly(depth, 3, raw = TRUE), data = df)

Residuals:
        1         2         3         4         5 
 0.111083 -0.208280  0.121497 -0.026035  0.001736 

Coefficients:
                             Estimate Std. Error t value Pr(>|t|)  
(Intercept)                    6.2571     0.4958  12.620   0.0503 .
poly(depth, 3, raw = TRUE)1  -60.9184    13.9633  -4.363   0.1434  
poly(depth, 3, raw = TRUE)2  256.3255    89.8197   2.854   0.2146  
poly(depth, 3, raw = TRUE)3 -350.0562   146.3810  -2.391   0.2521  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.2668 on 1 degrees of freedom
Multiple R-squared:  0.9943,    Adjusted R-squared:  0.977 
F-statistic: 57.69 on 3 and 1 DF,  p-value: 0.09641
lm_eqn <- function(df){
    m <- lm(amp ~ poly(depth,3,raw=TRUE), df);
    eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
         list(a = format(coef(m)[1], digits = 2), 
              b = format(coef(m)[2], digits = 2), 
             r2 = format(summary(m)$r.squared, digits = 3)))
    as.character(as.expression(eq));                 
}
p <- ggplot(data = plotampdepthdf, aes(x = depth, y = amp)) +
            geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x) +
            geom_point()
p1 <- p + geom_text(x = 0.2, y = 3, label = lm_eqn(plotampdepthdf), parse = TRUE) +
    xlab("Depth") + ylab("Amplitude") + ggtitle("Polynomial fit(Order 3)")
p1

Lets try to plot the predicted

plm_eqn <- function(df){
    m <- lm(amp ~ poly(depth,3,raw=TRUE), df);
    eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
         list(a = format(coef(m)[1], digits = 2), 
              b = format(coef(m)[2], digits = 2), 
             r2 = format(summary(m)$r.squared, digits = 3)))
    as.character(as.expression(eq));                 
}
predictedamps <- predict(poly.model,list(depth=plotampdepthdf$depth))
p <- ggplot(data = plotampdepthdf, aes(x = depth, y = amp)) +
            geom_point()
p1 <- p + geom_line(aes(x=depth,y=predictedamps)) +
     geom_text(x = 0.2, y = 3, label = plm_eqn(plotampdepthdf), parse = TRUE) +
     xlab("Depth") + ylab("Amplitude") + ggtitle("Predicted with actual")
p1

TODO - plot the tl vs depth

library(ggplot2)
lag <- c(5,3.6,2.5,1.5,.5)
depth <- c(0.025,0.05,.1,.2,.4)
plotampdepthdf <- data.frame(depth,amp)
lm_eqn <- function(df){
    m <- lm(amp ~ depth, df);
    eq <- substitute(italic(y) == a + b %.% italic(x)*","~~italic(r)^2~"="~r2, 
         list(a = format(coef(m)[1], digits = 2), 
              b = format(coef(m)[2], digits = 2), 
             r2 = format(summary(m)$r.squared, digits = 3)))
    as.character(as.expression(eq));                 
}
p <- ggplot(data = plotampdepthdf, aes(x = depth, y = amp)) +
            geom_smooth(method = "lm", se=FALSE, color="black", formula = y ~ x) +
            geom_point()
p1 <- p + geom_text(x = 0.2, y = 3, label = lm_eqn(plotampdepthdf), parse = TRUE)
p1

We need the time at which the maxima occurs, so do the lazy way to get the maxima by installing plotly to get visual cues.

blaygpfp %>% ggplot() +
  stat_smooth(aes(x = datetime, y = TatDpoint025,colour = as.factor(0.025)), se = FALSE) +
  stat_smooth(aes(x = datetime, y = TatDpoint05,colour = as.factor(0.05)), se = FALSE) +
  stat_smooth(aes(x = datetime, y = TatDpoint10,colour = as.factor(0.10)), se = FALSE) +
stat_smooth(aes(x = datetime, y = TatDpoint20,colour = as.factor(0.20)), se = FALSE) +
stat_smooth(aes(x = datetime, y = TatDpoint40,colour = as.factor(0.40)), se = FALSE) +
labs(colour = "Depth(m")  +
xlab("Date") + ylab("Temperature (deg C)")+
ggtitle("Soil Temperatures at various depths GPFP (O'Neil Nebraska) ")  

# check if line plot is better
ggplotly()
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
`geom_smooth()` using method = 'loess' and formula 'y ~ x'
unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'

Redo as line , but no smoothing

blaygpfp %>% ggplot() +
geom_line(aes(x=datetime,y=TatDpoint025,colour = as.factor(0.025))) +
geom_line(aes(x=datetime,y=TatDpoint05,colour = as.factor(0.05))) +
geom_line(aes(x=datetime,y=TatDpoint10,colour = as.factor(0.10))) +
geom_line(aes(x=datetime,y=TatDpoint20,colour = as.factor(0.20))) +
  geom_line(aes(x=datetime,y=TatDpoint40,colour = as.factor(0.40))) +
labs(colour = "Depth(m")  +
xlab("Date") + ylab("Temperature (deg C)")+
ggtitle("Soil Temperatures at various depths GPFP (O'Neil Nebraska) ")  

# check if line plot is better
ggplotly()
unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'unknown timezone 'zone/tz/2017c.1.0/zoneinfo/America/Los_Angeles'

Depth and time of the temperature

maxtempat <- c(14,16,16,20,4)
depth <- c(0.025,0.05,.1,.2,.4)
plothourdepthdf <- data.frame(depth,maxtempat)
p <- ggplot(data = plothourdepthdf, aes(x = depth, y = maxtempat)) +
            geom_point()
p

Very odd plot

try with hour start at 0

TODO - use - blaygpfp_melt df

Vertical soil temperatures at 0435, 0835, 1235,1635,2035 and 0035

library(lubridate)

fix the timestamp

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgZ2xvYmFsX29wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldCggd2FybmluZz1GQUxTRSkKYGBgClRoaXMgaXMgYW4gW1IgTWFya2Rvd25dKGh0dHA6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20pIE5vdGVib29rIHRvIHN0dWR5IGJvdW5kYXJ5IGxheWVyIG1ldGVvcm9sb2d5LgoKQ3JlYXRlIHRoZSBkYXRhc2V0IC0gLSBGcm9tIEdyZWF0IFBsYWlucyBGaWVsZCBQcnBncmFtIGF0IE8nTmVpbCBOZWJyYXNrYQpgYGB7cn0KVGF0RHBvaW50MDI1IDwtIGMoMjUuNTQsMjQuODQsMjUuNzcsMjkuNDIsMzMuMjUsMzUuMjUsMzQuODQsMzIuNjMsMzAuMDcsMjguNDIsMjcuMDksMjYuMDksMjUuMzApClRhdERwb2ludDA1IDwtIGMoMjYuMDAsMjUuMzAsMjUuMzUsMjcuMzYsMzAuMzIsMzIuNjMsMzMuMjAsMzIuMDUsMzAuMjAsMjguNzQsMjcuNTAsMjYuNjAsMjUuODMpCgpUYXREcG9pbnQxMCA8LSBjKDI2LjQyLDI1Ljg0LDI1LjQyLDI1Ljk4LDI3LjYyLDI5LjUyLDMwLjYyLDMwLjYyLDI5LjkxLDI4Ljg0LDI3Ljg0LDI3LjA2LDI2LjQwKQoKVGF0RHBvaW50MjAgPC0gYygyNi4zMiwyNS45NywyNS41NiwyNS4zOSwyNS41NywyNi4xMSwyNi44OCwyNy40MSwyNy42OCwyNy41NywyNy4yMiwyNi44NywyNi41MykKClRhdERwb2ludDQwIDwtIGMoMjQuNTAsMjQuNDgsMjQuMzYsMjQuMzQsMjQuMjcsMjQuMjQsMjQuMjYsMjQuMzIsMjQuNDcsMjQuNjQsMjQuNzMsMjQuNzgsMjQuODQpCgpkYXRldGltZSA8LSBjKCcyMDE1LTA4LTMxIDA0OjM1JywnMjAxNS0wOC0zMSAwNjozNScsJzIwMTUtMDgtMzEgMDg6MzUnLCcyMDE1LTA4LTMxIDEwOjM1JywnMjAxNS0wOC0zMSAxMjozNScsJzIwMTUtMDgtMzEgMTQ6MzUnLCcyMDE1LTA4LTMxIDE2OjM1JywnMjAxNS0wOC0zMSAxODozNScsJzIwMTUtMDgtMzEgMjA6MzUnLCcyMDE1LTA4LTMxIDIyOjM1JywnMjAxNS0wOS0wMSAwMDozNScsJzIwMTUtMDktMDEgMDI6MzUnLCcyMDE1LTA5LTAxIDA0OjM1JykgICAKCmJsYXlncGZwIDwtIGRhdGEuZnJhbWUoVGF0RHBvaW50MDI1LFRhdERwb2ludDA1LFRhdERwb2ludDEwLFRhdERwb2ludDIwLFRhdERwb2ludDQwLGRhdGV0aW1lKQoKYGBgCgpjaGVjayB0aGUgZGF0YQoKYGBge3J9CgojY29udmVydCB0aGUgZGF0ZSBmb3JtYXQKYmxheWdwZnAkZGF0ZXRpbWU8LSBhcy5QT1NJWGN0KGJsYXlncGZwJGRhdGV0aW1lLCAiJVktJW0tJWQgJUg6JU0iLHR6PSJVUy9QYWNpZmljIikKI1RPRE8gVGFrZSB0aGUgYW5ubm95aW5nIGRhdGUgZm90bWF0IGVycm9yIG91dApzdHIoYmxheWdwZnApCmBgYAoKClBsb3QgdGhlIGRhdGEKCmBgYHtyfQpwbG90KGJsYXlncGZwKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocmVzaGFwZSkKCmBgYAoKUGxvdCBUZW1wZXJhdHVyZSB3YXZlcyBhcyBmdW5jdGlvbiBvZiB0aW1lIGFuZCBkZXB0aC4KCmBgYHtyfQoKYmxheWdwZnAgJT4lIGdncGxvdCgpICsKZ2VvbV9wb2ludChhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDAyNSxjb2xvdXIgPSBhcy5mYWN0b3IoMC4wMjUpLCBzaGFwZT1hcy5mYWN0b3IoMCkpKSArCiAgc3RhdF9zbW9vdGgoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDAyNSksIHNlID0gRkFMU0UpICsKZ2VvbV9wb2ludChhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDA1LGNvbG91ciA9IGFzLmZhY3RvcigwLjA1KSkpICsKICBzdGF0X3Ntb290aChhZXMoeCA9IGRhdGV0aW1lLCB5ID0gVGF0RHBvaW50MDUpLCBzZSA9IEZBTFNFKSArCmdlb21fcG9pbnQoYWVzKHg9ZGF0ZXRpbWUseT1UYXREcG9pbnQxMCxjb2xvdXIgPSBhcy5mYWN0b3IoMC4xMCkpKSArCiAgc3RhdF9zbW9vdGgoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDEwKSwgc2UgPSBGQUxTRSkgKwpnZW9tX3BvaW50KGFlcyh4PWRhdGV0aW1lLHk9VGF0RHBvaW50MjAsY29sb3VyID0gYXMuZmFjdG9yKDAuMjApKSkgKwpzdGF0X3Ntb290aChhZXMoeCA9IGRhdGV0aW1lLCB5ID0gVGF0RHBvaW50MjApLCBzZSA9IEZBTFNFKSArCmdlb21fcG9pbnQoYWVzKHg9ZGF0ZXRpbWUseT1UYXREcG9pbnQ0MCxjb2xvdXIgPSBhcy5mYWN0b3IoMC40MCkpKSArCnN0YXRfc21vb3RoKGFlcyh4ID0gZGF0ZXRpbWUsIHkgPSBUYXREcG9pbnQ0MCksIHNlID0gRkFMU0UpICsKbGFicyhjb2xvdXIgPSAiRGVwdGgiKSAgKwp4bGFiKCJEYXRlIikgKyB5bGFiKCJUZW1wZXJhdHVyZSIpCiMgY2hlY2sgaWYgbGluZSBwbG90IGlzIGJldHRlcgoKYGBgCldpdGggbWFya2VycwpgYGB7cn0KI25vcm1hbGl6ZSB0ZW1wZXJhdHVyZQoKYmxheWdwZnAgJT4lIGdncGxvdCgpICsKZ2VvbV9wb2ludChhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDAyNSwgc2hhcGU9YXMuZmFjdG9yKDAuMDI1KSkpICsKICBnZW9tX2xpbmUoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDAyNSkpICsKZ2VvbV9wb2ludChhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDA1LHNoYXBlID0gYXMuZmFjdG9yKDAuMDUpKSkgKwogIGdlb21fbGluZShhZXMoeCA9IGRhdGV0aW1lLCB5ID0gVGF0RHBvaW50MDUpKSArCmdlb21fcG9pbnQoYWVzKHg9ZGF0ZXRpbWUseT1UYXREcG9pbnQxMCxzaGFwZSA9IGFzLmZhY3RvcigwLjEwKSkpICsKICBnZW9tX2xpbmUoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDEwKSwpICsKZ2VvbV9wb2ludChhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDIwLHNoYXBlID0gYXMuZmFjdG9yKDAuMjApKSkgKwpnZW9tX2xpbmUoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDIwKSkgKwpnZW9tX3BvaW50KGFlcyh4PWRhdGV0aW1lLHk9VGF0RHBvaW50NDAsc2hhcGUgPSBhcy5mYWN0b3IoMC40MCkpKSArCmdlb21fbGluZShhZXMoeCA9IGRhdGV0aW1lLCB5ID0gVGF0RHBvaW50NDApKSArCmxhYnMoY29sb3VyID0gIkRlcHRoIikgICsKeGxhYigiRGF0ZSIpICsgeWxhYigiVGVtcGVyYXR1cmUiKSsKZ2d0aXRsZSgiVGVtcGVyYXR1cmVzIHdhdmVzIC0gZnVuY3Rpb24gb2YgdGltZSBhbmQgZGVwdGgiKSAgCiMgY2hlY2sgaWYgbGluZSBwbG90IGlzIGJldHRlcgoKCmBgYAoKCkhvdXNla2VlcGluZwoKYGBge3J9CiMgcmVzaGFwZSBpdApibGF5Z3BmcF9tZWx0IDwtIG1lbHQoYmxheWdwZnAsaWQ9ImRhdGV0aW1lIikKCiMgc2V0IHRoZSBkZXB0aApibGF5Z3BmcF9tZWx0JGRlcHRoIDwtIDAKYmxheWdwZnBfbWVsdFtibGF5Z3BmcF9tZWx0JHZhcmlhYmxlPT0nVGF0RHBvaW50MDUnLF0kZGVwdGggPSAwLjA1CmJsYXlncGZwX21lbHRbYmxheWdwZnBfbWVsdCR2YXJpYWJsZT09J1RhdERwb2ludDEwJyxdJGRlcHRoID0gMC4xMApibGF5Z3BmcF9tZWx0W2JsYXlncGZwX21lbHQkdmFyaWFibGU9PSdUYXREcG9pbnQyMCcsXSRkZXB0aCA9IDAuMjAKYmxheWdwZnBfbWVsdFtibGF5Z3BmcF9tZWx0JHZhcmlhYmxlPT0nVGF0RHBvaW50NDAnLF0kZGVwdGggPSAwLjQwCmJsYXlncGZwX21lbHRbYmxheWdwZnBfbWVsdCR2YXJpYWJsZT09J1RhdERwb2ludDAyNScsXSRkZXB0aCA9IDAuMDI1CmxpYnJhcnkobHVicmlkYXRlKQojSW4gY2hlY2tfdHpvbmVzKGUxLCBlMikgOiAndHpvbmUnIGF0dHJpYnV0ZXMgYXJlIGluY29uc2lzdGVudApibGF5Z3BmcF9tZWx0JGRhdGV0aW1lIDwtIHltZF9obXMoYmxheWdwZnBfbWVsdCRkYXRldGltZSkKCiNEbyBpbmNyZW1lbnQgb2YgdGhlIHRpbWUgaW50ZXJ2YWxzCmJsYXlncGZwX21lbHQgJT4lIGZpbHRlcihkYXRldGltZSA9PSB5bWRfaG1zKCIyMDE1LTA5LTAxIDA0OjM1OjAwIikpIAoKIyBzZXQgdGhlIHRpbWUgaW50ZXJ2YWxzCiBibGF5Z3BmcF9tZWx0JGludGVydmFsIDwtIDAKYmxheWdwZnBfbWVsdFtkYXRldGltZSA9PSB5bWRfaG1zKCIyMDE1LTA4LTMxIDA2OjM1OjAwIiksIF0kaW50ZXJ2YWw8LSAyCmJsYXlncGZwX21lbHRbZGF0ZXRpbWUgPT0geW1kX2htcygiMjAxNS0wOC0zMSAwODozNTowMCIpLCBdJGludGVydmFsPC0gNApibGF5Z3BmcF9tZWx0W2RhdGV0aW1lID09IHltZF9obXMoIjIwMTUtMDgtMzEgMTA6MzU6MDAiKSwgXSRpbnRlcnZhbDwtIDYKYmxheWdwZnBfbWVsdFtkYXRldGltZSA9PSB5bWRfaG1zKCIyMDE1LTA4LTMxIDEyOjM1OjAwIiksIF0kaW50ZXJ2YWw8LSA4CmJsYXlncGZwX21lbHRbZGF0ZXRpbWUgPT0geW1kX2htcygiMjAxNS0wOC0zMSAxNDozNTowMCIpLCBdJGludGVydmFsPC0gMTAKYmxheWdwZnBfbWVsdFtkYXRldGltZSA9PSB5bWRfaG1zKCIyMDE1LTA4LTMxIDE2OjM1OjAwIiksIF0kaW50ZXJ2YWw8LSAxMgpibGF5Z3BmcF9tZWx0W2RhdGV0aW1lID09IHltZF9obXMoIjIwMTUtMDgtMzEgMTg6MzU6MDAiKSwgXSRpbnRlcnZhbDwtIDE0CmJsYXlncGZwX21lbHRbZGF0ZXRpbWUgPT0geW1kX2htcygiMjAxNS0wOC0zMSAyMDozNTowMCIpLCBdJGludGVydmFsPC0gMTYKYmxheWdwZnBfbWVsdFtkYXRldGltZSA9PSB5bWRfaG1zKCIyMDE1LTA4LTMxIDIyOjM1OjAwIiksIF0kaW50ZXJ2YWw8LSAxOApibGF5Z3BmcF9tZWx0W2RhdGV0aW1lID09IHltZF9obXMoIjIwMTUtMDktMDEgMDA6MzU6MDAiKSwgXSRpbnRlcnZhbDwtIDIwCmJsYXlncGZwX21lbHRbZGF0ZXRpbWUgPT0geW1kX2htcygiMjAxNS0wOS0wMSAwMjozNTowMCIpLCBdJGludGVydmFsPC0gMjIKYmxheWdwZnBfbWVsdFtkYXRldGltZSA9PSB5bWRfaG1zKCIyMDE1LTA5LTAxIDA0OjM1OjAwIiksIF0kaW50ZXJ2YWw8LSAyNAoKCiMnZGF0YS5mcmFtZSc6CTY1IG9icy4gb2YgIDMgdmFyaWFibGVzOgojICQgZGF0ZXRpbWU6IFBPU0lYY3QsIGZvcm1hdDogIjIwMTUtMDgtMzEgMDQ6MzU6MDAiICIyMDE1LTA4LTMxIDA2OjM1OjAwIiAgIyQgdmFyaWFibGU6IEZhY3RvciB3LyA1IGxldmVscyAiVGF0RHBvaW50MDI1IiwuLjogMSAxIDEgMSAxIDEgMSAxIDEgMSAuLi4KIyAkIHZhbHVlICAgOiBudW0gIDI1LjUgMjQuOCAyNS44IDI5LjQgMzMuMiAuLi4KCgoKYGBgCgpQbG90IFRpbWUgd2F2ZXMgYXMgZnVuY3Rpb24gb2YgZGVwdGggYW5kIHRlbXBlcmF0dXJlCmBgYHtyfQojbm9ybWFsaXplIHRlbXBlcmF0dXJlCmJsYXlncGZwX21lbHQkc2NhbGVUIDwtIHNjYWxlKGJsYXlncGZwX21lbHQkdmFsdWUpICAlPiUgYXMudmVjdG9yKCkKIyBXZSB3YW50IGZvciBob3VycyAwLCA0LDgsMTIsMTYsMjAKYmxheWdwZnBfbWVsdCAgJT4lIGZpbHRlcihpbnRlcnZhbCAlaW4lIGMoMCwgNCw4LDEyLDE2LDIwKSkgJT4lICBnZ3Bsb3QoKSArCmdlb21fcG9pbnQoYWVzKHg9dmFsdWUseT1kZXB0aCxjb2xvcj1hcy5mYWN0b3IoaW50ZXJ2YWwpLHNoYXBlPWFzLmZhY3RvcihpbnRlcnZhbCkpKSsKICAgCiNnZW9tX2xpbmUoYWVzKHg9dmFsdWUseT1kZXB0aCxjb2xvcj1hcy5mYWN0b3IoaW50ZXJ2YWwpLHNoYXBlPWFzLmZhY3RvcihpbnRlcnZhbCkpKSsKc3RhdF9zbW9vdGgoYWVzKHg9dmFsdWUseT1kZXB0aCxjb2xvcj1hcy5mYWN0b3IoaW50ZXJ2YWwpLHNoYXBlPWFzLmZhY3RvcihpbnRlcnZhbCkpKSsgIAp4bGFiKCJUZW1wZXJhdHVyZShkZWcgQykiKSArIHlsYWIoIkRlcHRoIikrCmdndGl0bGUoIlRlbXBlcmF0dXJlcyBhdCB2YXJpb3VzIHRpbWVzIC0gZnVuY3Rpb24gb2YgeiBhbmQgVCIpICAKIyBjaGVjayBpZiBsaW5lIHBsb3QgaXMgYmV0dGVyCmBgYAoKIyBwbG90IGZvciBkZXB0aApgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKYW1wIDwtIGMoNSwzLjYsMi41LDEuNSwuNSkKZGVwdGggPC0gYygwLjAyNSwwLjA1LC4xLC4yLC40KQoKcGxvdGFtcGRlcHRoZGYgPC0gZGF0YS5mcmFtZShkZXB0aCxhbXApCgpsbV9lcW4gPC0gZnVuY3Rpb24oZGYpewogICAgbSA8LSBsbShhbXAgfiBkZXB0aCwgZGYpOwogICAgZXEgPC0gc3Vic3RpdHV0ZShpdGFsaWMoeSkgPT0gYSArIGIgJS4lIGl0YWxpYyh4KSoiLCJ+fml0YWxpYyhyKV4yfiI9In5yMiwgCiAgICAgICAgIGxpc3QoYSA9IGZvcm1hdChjb2VmKG0pWzFdLCBkaWdpdHMgPSAyKSwgCiAgICAgICAgICAgICAgYiA9IGZvcm1hdChjb2VmKG0pWzJdLCBkaWdpdHMgPSAyKSwgCiAgICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwgZGlnaXRzID0gMykpKQogICAgYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKTsgICAgICAgICAgICAgICAgIAp9CnAgPC0gZ2dwbG90KGRhdGEgPSBwbG90YW1wZGVwdGhkZiwgYWVzKHggPSBkZXB0aCwgeSA9IGFtcCkpICsKICAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2U9RkFMU0UsIGNvbG9yPSJibGFjayIsIGZvcm11bGEgPSB5IH4geCkgKwogICAgICAgICAgICBnZW9tX3BvaW50KCkKcDEgPC0gcCArIGdlb21fdGV4dCh4ID0gMC4yLCB5ID0gMywgbGFiZWwgPSBsbV9lcW4ocGxvdGFtcGRlcHRoZGYpLCBwYXJzZSA9IFRSVUUpCnAxCmBgYApXaXRoIGxvZyBBbXAKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKCmFtcCA8LSBjKDUsMy42LDIuNSwxLjUsLjUpCmRlcHRoIDwtIGMoMC4wMjUsMC4wNSwuMSwuMiwuNCkKCmFtcCA8LSBsb2coYW1wKQpwbG90YW1wZGVwdGhkZiA8LSBkYXRhLmZyYW1lKGRlcHRoLGFtcCkKCmxtX2VxbiA8LSBmdW5jdGlvbihkZil7CiAgICBtIDwtIGxtKGFtcCB+IGRlcHRoLCBkZik7CiAgICBlcSA8LSBzdWJzdGl0dXRlKGl0YWxpYyh5KSA9PSBhICsgYiAlLiUgaXRhbGljKHgpKiIsIn5+aXRhbGljKHIpXjJ+Ij0ifnIyLCAKICAgICAgICAgbGlzdChhID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLCAKICAgICAgICAgICAgICBiID0gZm9ybWF0KGNvZWYobSlbMl0sIGRpZ2l0cyA9IDIpLCAKICAgICAgICAgICAgIHIyID0gZm9ybWF0KHN1bW1hcnkobSkkci5zcXVhcmVkLCBkaWdpdHMgPSAzKSkpCiAgICBhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpOyAgICAgICAgICAgICAgICAgCn0KcCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RhbXBkZXB0aGRmLCBhZXMoeCA9IGRlcHRoLCB5ID0gYW1wKSkgKwogICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSwgY29sb3I9ImJsYWNrIiwgZm9ybXVsYSA9IHkgfiB4KSArCiAgICAgICAgICAgIGdlb21fcG9pbnQoKQpwMSA8LSBwICsgZ2VvbV90ZXh0KHggPSAwLjIsIHkgPSAuNSwgbGFiZWwgPSBsbV9lcW4ocGxvdGFtcGRlcHRoZGYpLCBwYXJzZSA9IFRSVUUpKwogICAgeGxhYigiRGVwdGgiKSArIHlsYWIoImxvZyhhbXBsaXR1ZGUpIikgKyBnZ3RpdGxlKCJMb2cgb2YgQW1wbGl0dWRlIikKcDEKYGBgCiNMZXRzIHRyeSBhIHBvbHlub21pYWwgZml0CiNsbSh5IH4gcG9seSh4LCAzLCByYXc9VFJVRSkpCmBgYHtyfQoKYW1wIDwtIGMoNSwzLjYsMi41LDEuNSwuNSkKZGVwdGggPC0gYygwLjAyNSwwLjA1LC4xLC4yLC40KQoKcGxvdGFtcGRlcHRoZGYgPC0gZGF0YS5mcmFtZShkZXB0aCxhbXApCnBvbHkubW9kZWwgPC1sbShhbXAgfiBwb2x5KGRlcHRoLDMscmF3PVRSVUUpLCBkZikKc3VtbWFyeShwb2x5Lm1vZGVsKQpsbV9lcW4gPC0gZnVuY3Rpb24oZGYpewogICAgbSA8LSBsbShhbXAgfiBwb2x5KGRlcHRoLDMscmF3PVRSVUUpLCBkZik7CiAgICBlcSA8LSBzdWJzdGl0dXRlKGl0YWxpYyh5KSA9PSBhICsgYiAlLiUgaXRhbGljKHgpKiIsIn5+aXRhbGljKHIpXjJ+Ij0ifnIyLCAKICAgICAgICAgbGlzdChhID0gZm9ybWF0KGNvZWYobSlbMV0sIGRpZ2l0cyA9IDIpLCAKICAgICAgICAgICAgICBiID0gZm9ybWF0KGNvZWYobSlbMl0sIGRpZ2l0cyA9IDIpLCAKICAgICAgICAgICAgIHIyID0gZm9ybWF0KHN1bW1hcnkobSkkci5zcXVhcmVkLCBkaWdpdHMgPSAzKSkpCiAgICBhcy5jaGFyYWN0ZXIoYXMuZXhwcmVzc2lvbihlcSkpOyAgICAgICAgICAgICAgICAgCn0KcCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RhbXBkZXB0aGRmLCBhZXMoeCA9IGRlcHRoLCB5ID0gYW1wKSkgKwogICAgICAgICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZT1GQUxTRSwgY29sb3I9ImJsYWNrIiwgZm9ybXVsYSA9IHkgfiB4KSArCiAgICAgICAgICAgIGdlb21fcG9pbnQoKQpwMSA8LSBwICsgZ2VvbV90ZXh0KHggPSAwLjIsIHkgPSAzLCBsYWJlbCA9IGxtX2VxbihwbG90YW1wZGVwdGhkZiksIHBhcnNlID0gVFJVRSkgKwogICAgeGxhYigiRGVwdGgiKSArIHlsYWIoIkFtcGxpdHVkZSIpICsgZ2d0aXRsZSgiUG9seW5vbWlhbCBmaXQoT3JkZXIgMykiKQpwMQpgYGAKIyBMZXRzIHRyeSB0byBwbG90IHRoZSBwcmVkaWN0ZWQgCmBgYHtyfQoKcGxtX2VxbiA8LSBmdW5jdGlvbihkZil7CiAgICBtIDwtIGxtKGFtcCB+IHBvbHkoZGVwdGgsMyxyYXc9VFJVRSksIGRmKTsKICAgIGVxIDwtIHN1YnN0aXR1dGUoaXRhbGljKHkpID09IGEgKyBiICUuJSBpdGFsaWMoeCkqIiwifn5pdGFsaWMocileMn4iPSJ+cjIsIAogICAgICAgICBsaXN0KGEgPSBmb3JtYXQoY29lZihtKVsxXSwgZGlnaXRzID0gMiksIAogICAgICAgICAgICAgIGIgPSBmb3JtYXQoY29lZihtKVsyXSwgZGlnaXRzID0gMiksIAogICAgICAgICAgICAgcjIgPSBmb3JtYXQoc3VtbWFyeShtKSRyLnNxdWFyZWQsIGRpZ2l0cyA9IDMpKSkKICAgIGFzLmNoYXJhY3Rlcihhcy5leHByZXNzaW9uKGVxKSk7ICAgICAgICAgICAgICAgICAKfQpwcmVkaWN0ZWRhbXBzIDwtIHByZWRpY3QocG9seS5tb2RlbCxsaXN0KGRlcHRoPXBsb3RhbXBkZXB0aGRmJGRlcHRoKSkKcCA8LSBnZ3Bsb3QoZGF0YSA9IHBsb3RhbXBkZXB0aGRmLCBhZXMoeCA9IGRlcHRoLCB5ID0gYW1wKSkgKwogICAgICAgICAgICBnZW9tX3BvaW50KCkKcDEgPC0gcCArIGdlb21fbGluZShhZXMoeD1kZXB0aCx5PXByZWRpY3RlZGFtcHMpKSArCiAgICAgZ2VvbV90ZXh0KHggPSAwLjIsIHkgPSAzLCBsYWJlbCA9IHBsbV9lcW4ocGxvdGFtcGRlcHRoZGYpLCBwYXJzZSA9IFRSVUUpICsKICAgICB4bGFiKCJEZXB0aCIpICsgeWxhYigiQW1wbGl0dWRlIikgKyBnZ3RpdGxlKCJQcmVkaWN0ZWQgd2l0aCBhY3R1YWwiKQpwMQoKYGBgCgoKI1RPRE8gLSBwbG90IHRoZSB0bCB2cyBkZXB0aApgYGB7cn0KbGlicmFyeShnZ3Bsb3QyKQoKbGFnIDwtIGMoNSwzLjYsMi41LDEuNSwuNSkKZGVwdGggPC0gYygwLjAyNSwwLjA1LC4xLC4yLC40KQoKcGxvdGFtcGRlcHRoZGYgPC0gZGF0YS5mcmFtZShkZXB0aCxhbXApCgpsbV9lcW4gPC0gZnVuY3Rpb24oZGYpewogICAgbSA8LSBsbShhbXAgfiBkZXB0aCwgZGYpOwogICAgZXEgPC0gc3Vic3RpdHV0ZShpdGFsaWMoeSkgPT0gYSArIGIgJS4lIGl0YWxpYyh4KSoiLCJ+fml0YWxpYyhyKV4yfiI9In5yMiwgCiAgICAgICAgIGxpc3QoYSA9IGZvcm1hdChjb2VmKG0pWzFdLCBkaWdpdHMgPSAyKSwgCiAgICAgICAgICAgICAgYiA9IGZvcm1hdChjb2VmKG0pWzJdLCBkaWdpdHMgPSAyKSwgCiAgICAgICAgICAgICByMiA9IGZvcm1hdChzdW1tYXJ5KG0pJHIuc3F1YXJlZCwgZGlnaXRzID0gMykpKQogICAgYXMuY2hhcmFjdGVyKGFzLmV4cHJlc3Npb24oZXEpKTsgICAgICAgICAgICAgICAgIAp9CnAgPC0gZ2dwbG90KGRhdGEgPSBwbG90YW1wZGVwdGhkZiwgYWVzKHggPSBkZXB0aCwgeSA9IGFtcCkpICsKICAgICAgICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2U9RkFMU0UsIGNvbG9yPSJibGFjayIsIGZvcm11bGEgPSB5IH4geCkgKwogICAgICAgICAgICBnZW9tX3BvaW50KCkKcDEgPC0gcCArIGdlb21fdGV4dCh4ID0gMC4yLCB5ID0gMywgbGFiZWwgPSBsbV9lcW4ocGxvdGFtcGRlcHRoZGYpLCBwYXJzZSA9IFRSVUUpCnAxCmBgYAoKV2UgbmVlZCB0aGUgdGltZSBhdCB3aGljaCB0aGUgbWF4aW1hIG9jY3Vycywgc28gZG8gdGhlIGxhenkgd2F5IHRvIGdldCB0aGUgbWF4aW1hIGJ5IGluc3RhbGxpbmcgcGxvdGx5IHRvIGdldCB2aXN1YWwgY3Vlcy4KCmBgYHtyfQpsaWJyYXJ5KHBsb3RseSkKYmxheWdwZnAgJT4lIGdncGxvdCgpICsKCiAgc3RhdF9zbW9vdGgoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDAyNSxjb2xvdXIgPSBhcy5mYWN0b3IoMC4wMjUpKSwgc2UgPSBGQUxTRSkgKwoKICBzdGF0X3Ntb290aChhZXMoeCA9IGRhdGV0aW1lLCB5ID0gVGF0RHBvaW50MDUsY29sb3VyID0gYXMuZmFjdG9yKDAuMDUpKSwgc2UgPSBGQUxTRSkgKwoKICBzdGF0X3Ntb290aChhZXMoeCA9IGRhdGV0aW1lLCB5ID0gVGF0RHBvaW50MTAsY29sb3VyID0gYXMuZmFjdG9yKDAuMTApKSwgc2UgPSBGQUxTRSkgKwoKc3RhdF9zbW9vdGgoYWVzKHggPSBkYXRldGltZSwgeSA9IFRhdERwb2ludDIwLGNvbG91ciA9IGFzLmZhY3RvcigwLjIwKSksIHNlID0gRkFMU0UpICsKCnN0YXRfc21vb3RoKGFlcyh4ID0gZGF0ZXRpbWUsIHkgPSBUYXREcG9pbnQ0MCxjb2xvdXIgPSBhcy5mYWN0b3IoMC40MCkpLCBzZSA9IEZBTFNFKSArCmxhYnMoY29sb3VyID0gIkRlcHRoKG0iKSAgKwp4bGFiKCJEYXRlIikgKyB5bGFiKCJUZW1wZXJhdHVyZSAoZGVnIEMpIikrCmdndGl0bGUoIlNvaWwgVGVtcGVyYXR1cmVzIGF0IHZhcmlvdXMgZGVwdGhzIEdQRlAgKE8nTmVpbCBOZWJyYXNrYSkgIikgIAojIGNoZWNrIGlmIGxpbmUgcGxvdCBpcyBiZXR0ZXIKCmdncGxvdGx5KCkKYGBgCgojIFJlZG8gYXMgbGluZSAsIGJ1dCBubyBzbW9vdGhpbmcgCgpgYGB7cn0KCmJsYXlncGZwICU+JSBnZ3Bsb3QoKSArCmdlb21fbGluZShhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDAyNSxjb2xvdXIgPSBhcy5mYWN0b3IoMC4wMjUpKSkgKwpnZW9tX2xpbmUoYWVzKHg9ZGF0ZXRpbWUseT1UYXREcG9pbnQwNSxjb2xvdXIgPSBhcy5mYWN0b3IoMC4wNSkpKSArCmdlb21fbGluZShhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDEwLGNvbG91ciA9IGFzLmZhY3RvcigwLjEwKSkpICsKZ2VvbV9saW5lKGFlcyh4PWRhdGV0aW1lLHk9VGF0RHBvaW50MjAsY29sb3VyID0gYXMuZmFjdG9yKDAuMjApKSkgKwogIGdlb21fbGluZShhZXMoeD1kYXRldGltZSx5PVRhdERwb2ludDQwLGNvbG91ciA9IGFzLmZhY3RvcigwLjQwKSkpICsKbGFicyhjb2xvdXIgPSAiRGVwdGgobSIpICArCnhsYWIoIkRhdGUiKSArIHlsYWIoIlRlbXBlcmF0dXJlIChkZWcgQykiKSsKZ2d0aXRsZSgiU29pbCBUZW1wZXJhdHVyZXMgYXQgdmFyaW91cyBkZXB0aHMgR1BGUCAoTydOZWlsIE5lYnJhc2thKSAiKSAgCiMgY2hlY2sgaWYgbGluZSBwbG90IGlzIGJldHRlcgpnZ3Bsb3RseSgpCmBgYAoKI0RlcHRoIGFuZCB0aW1lIG9mIHRoZSB0ZW1wZXJhdHVyZQpgYGB7cn0KbWF4dGVtcGF0IDwtIGMoMTQsMTYsMTYsMjAsNCkKZGVwdGggPC0gYygwLjAyNSwwLjA1LC4xLC4yLC40KQoKcGxvdGhvdXJkZXB0aGRmIDwtIGRhdGEuZnJhbWUoZGVwdGgsbWF4dGVtcGF0KQpwIDwtIGdncGxvdChkYXRhID0gcGxvdGhvdXJkZXB0aGRmLCBhZXMoeCA9IGRlcHRoLCB5ID0gbWF4dGVtcGF0KSkgKwogICAgICAgICAgICBnZW9tX3BvaW50KCkKcApgYGAKI1Zlcnkgb2RkIHBsb3QKCiMgdHJ5IHdpdGggaG91ciBzdGFydCBhdCAwCiNUT0RPIC0gdXNlIC0gIGJsYXlncGZwX21lbHQgZGYKCgoKClZlcnRpY2FsIHNvaWwgdGVtcGVyYXR1cmVzIGF0IDA0MzUsIDA4MzUsIDEyMzUsMTYzNSwyMDM1IGFuZCAwMDM1CmBgYHtyfQpsaWJyYXJ5KGx1YnJpZGF0ZSkKCgpgYGAKCmBgYHtyfQoKCmBgYAoKZml4IHRoZSB0aW1lc3RhbXAKCmBgYHtyfQoKYGBg